//310323878 - Created By Ronny Remesnik last update : 19-05-2009
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#pragma warning (disable: 4996)

#define MAX_STRING 100
#define MAX_ARGS 10
//#define ONLY_ONE

#define ROWS 5 
#define BITS 5
#define BITSALLOC ((BITS % 8) + 7)/8 + BITS / 8  //Formula CopyRights - Alon - Thanks.

typedef unsigned char byte;
typedef enum EWORDS {FIRST, SECOND, THIRD, FORTH,FIFTH} mywords;
const char *senum[] = {"FIRST","SECOND","THIRD","FORTH","FIFTH"};

typedef char **pStrings;
// Tar 1 Functions...
void tar1();
char * get_Strings(char **words,int n,...);

// Tar 2 Functions...
void tar2();
char * bytetostring(byte b,int size);
void bitmatrix(byte mat[][BITSALLOC],int x,int y,int flag);
void printmatrix(byte mat[][BITSALLOC]);
byte getbitcount(byte b);


char * get_Strings(char **words,int n,...)
{
	va_list lmain,lsec;
	char *ret,word[MAX_STRING],currentrow[MAX_STRING],*currentword,searchrow[MAX_STRING],*searchword,savedrow[MAX_STRING];
	int i,j,max_length=0,word_count=0,word_jump=0;

	ret = (char *)malloc(1);
	strcpy(ret,"");			//make empty
	strcpy((*words),"");    // make empty
	va_start(lmain,n);      //init main param list
	for(i=0;i<n;i++)
	{
  		strcpy(currentrow,va_arg(lmain,char*));    // copy param row
		strcpy(currentrow,strlwr(currentrow));     // convert to lower
		strcpy(savedrow,currentrow);			   // save to temp	
		currentword = strtok (currentrow," ,");    // search for words
		word_jump = 0;								// count words in row to jump
		while (currentword != NULL)					// while still have word
		{
		 va_start(lsec,n);						// init second list
  		 word_count=0;						    //count current word in all rows
		 for(j=0;j<n;j++)
		 {
	  		 strcpy(searchrow,strlwr(va_arg(lsec,char*)));	// check for each row
			 searchword = strtok (searchrow," ,");			// read the word
			 while (searchword != NULL)						// while have words in row
			 {
				 if (strcmp(searchword,currentword)==0)		//if words equal , increase the counter
					 word_count++;
				 
				 if (word_count>1)							// when bigger than one, word exist more than 1 time
				 {
					 strcpy(word,searchword);				//copy to temp word
					 strcat(word," ");						//add space
					 if (strstr(ret,word)==NULL)			//check for existence, add in not already exist
					 {
						 max_length = (int)strlen(ret);		//check the current length
						 ret = (char *)realloc(ret,(int)strlen(ret) + (int)strlen(word) + 1);// realloc memory
						 ret[max_length] = 0;				//put the end sign
						 strcat(ret,word);					//concat the found word to the total string
						}
					 
					 break;									//because word already exist, no need to check more
				 }
				 searchword = strtok (NULL," ,");			// search for next word	
			 }//end while
		
		 }//end for

		 if (word_count==1)		//when word exist only one time
		 {  // add the word to the total exist words string - *(words)
			 max_length = (int)strlen((*words));
			(*words) = (char *)realloc((*words),(int)strlen((*words)) + (int)strlen(currentword)+2);
			(*words)[max_length] = 0;
			strcat((*words),currentword);
			strcat((*words)," ");
		 }

		 word_jump++;					//for each checked word, need to skip the already checked words, because searching always from the begining.
		 strcpy(currentrow,savedrow);   //reassign the current row
		 currentword = strtok (currentrow, " ,"); //searching from begining        
		 for(j=0;j<word_jump;j++)					//skipping the already checked words
			currentword = strtok (NULL, " ,");        
		 va_end(lsec);				//end the current list, will open it again when word exist

		}// end while
	
	}// end for
	va_end(lmain); // close the main param list
	
	max_length = (int)strlen(ret);
	if (max_length>0)		//when repeat words found, concat them to the *words variable, to achieve string with all words that exist only once.
	{
		max_length = (int)strlen(*words);
		(*words) = (char *)realloc((*words),(int)strlen((*words)) + (int)strlen(ret) + 1);
		(*words)[max_length] = 0;
		strcat((*words),ret);
	}
return ret;

}


void tar1()
{
pStrings arr=NULL;
char *s=NULL,tmp[MAX_STRING],*ret,*words;
int i=0,max,count=0;
#ifdef ONLY_ONE
mywords num;
#endif

do
{
	printf("Please Start Enter String (%d)...\n",count+1);
	fflush(stdin);
	gets(tmp);
	if (strlen(tmp)==0)
		break;
	count++;
	arr = (pStrings)realloc(arr,sizeof(char *)*(count));
	arr[count-1] = (char *)malloc(sizeof(char)*strlen(tmp));
	strcpy(arr[count-1],tmp);
}
while (1);

if ((strlen(tmp)==0) && (count==0))
{
	printf("Strings Not Entered...\n");
	return;
}

words = (char *)malloc(0);
ret = get_Strings(&words,count,arr[0],arr[1],arr[2],arr[3],arr[4],
    						   arr[5],arr[6],arr[7],arr[8],arr[9]);	

printf("Repeated Words : %s\n",strupr(ret));

max = (sizeof(senum) / sizeof(senum[0])); // calc the array size

#ifdef ONLY_ONE
printf("Please Select from the menu...\n");
printf("%d : %s\n",i+1,senum[FIRST]);
printf("%d : %s\n",i+2,senum[SECOND]);
printf("%d : %s\n",i+3,senum[THIRD]);
printf("%d : %s\n",i+4,senum[FORTH]);
printf("%d : %s\n",i+5,senum[FIFTH]);

fflush(stdin);
scanf("%d",&num);
num--; // index start from 1, array from 0

printf("The Strings That Contain The Word [%s] are : \n",senum[num]);
strcpy(tmp,senum[num]);
s = (char *)malloc((int)strlen(senum[num]));
s = strlwr(tmp); //convert to lower case

for(i=0;i<count;i++)
	if (strstr(strlwr(arr[i]),s))
		printf("(%s).\n",arr[i]);

#endif

#ifndef ONLY_ONE
printf("All Words : \n");
printf("%s.\n",strupr(words));
printf("Repeated Words : \n");
printf("%s.\n",ret);

#endif

// Free the allocations.
if (words!=NULL)
 free(words);

free(ret);

}

char * bytetostring(byte b,int size)
{
char *tmp;
int i;
tmp =(char *) malloc(size);
// step on the byte, by size, add 1 or 0 to the string
for (i=0;i<size;i++)
	tmp[i] = ( b & (1<<i) )?('1'):('0');

tmp[size]=0;
return tmp;
}

void bitmatrix(byte mat[][BITSALLOC],int x,int y,int flag)
{

byte mask;
int byteindex,bitindex;
x--;
byteindex = (x / 8);
bitindex = x % 8;
if (flag==0)
{ // set to 0 - and
  mask = 255 - (1<<(bitindex));
  mat[y-1][byteindex]&=mask;
}
else
{
  //set 1 = or
  mask = 1<<(bitindex);
  mat[y-1][byteindex]|=mask;
}

}

void printmatrix(byte mat[][BITSALLOC])
{
int i,j;
for(i=0;i<ROWS;i++)
{
	// print the bytes converted to strings. on the last one change the size
	for(j=0;j<BITSALLOC;j++)
		printf("%s ",bytetostring(mat[i][j],(j==BITSALLOC-1)?((BITS % 8) ):(8)) );
	printf("\n");
}
}
byte getbitcount(byte b)
{
int i;
byte res=0;
// step on each bit and add 1 if there is one on the i position
for (i=0;i<7;i++)
	res += ((1<<i) & b)?(1):(0);
return res;

}
void tar2()
{
byte mat[ROWS][BITSALLOC]; // bytes array. sizes are constants using formulas..
int count=0,i,j;
int x,y,flag;

// make empty
for(i=0;i<ROWS;i++)
	for(j=0;j<BITSALLOC;j++)
		mat[i][j] = 0;

do
{
	printf("Insert X , Y , Flag (example : 1 1 1)...\n");
	scanf("%d %d %d",&x,&y,&flag);
	if (x==0 && y==0 && flag==0)
		break;
	bitmatrix(mat,x,y,flag);
	printmatrix(mat);


}
while (1);

for(i=0;i<ROWS;i++)
	for(j=0;j<BITSALLOC;j++)
		count += getbitcount(mat[i][j]);

printf("Total Bits On : %d .\n", count);

if (count%2==0)
{
	for(j=0;j<BITSALLOC;j++)
		mat[0][j]&= mat[1][j];
}
else
	for(j=0;j<BITSALLOC;j++)
		mat[2][j]|= mat[3][j];


printf("Result Table : \n");
printmatrix(mat);

}

void main()
{
int num;

do
{
	printf("Select Program :\n");
	printf("1. String  & Words :\n");
	printf("2. BitWise Operation :\n");
	printf("3. Quit :\n");

    scanf("%d",&num);
	switch (num)
	{
	case 1: tar1();break;
	case 2: tar2();break;
	case 3: exit(1);
	}

}
while(1);

}